home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / o_init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  9.6 KB  |  361 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)o_init.c    3.1    93/05/25    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include    "hack.h"        /* for typedefs */
  6.  
  7. static void NDECL(setgemprobs);
  8. static void FDECL(shuffle,(int,int,BOOLEAN_P));
  9. static boolean FDECL(interesting_to_discover,(int));
  10.  
  11. /* note that NROFOBJECTS is the number of legal objects, which does not count
  12.  * the strange object and null object that take up positions 0 and NROFOBJECTS+1
  13.  * in the objects array
  14.  */
  15. #define TOTAL_OBJS    (NROFOBJECTS+2)
  16.  
  17. const char obj_symbols[] = {
  18.     ILLOBJ_CLASS, AMULET_CLASS, GOLD_CLASS, FOOD_CLASS, WEAPON_CLASS,
  19.     TOOL_CLASS, BALL_CLASS, CHAIN_CLASS, ROCK_CLASS, ARMOR_CLASS,
  20.     POTION_CLASS, SCROLL_CLASS, WAND_CLASS,
  21.     SPBOOK_CLASS, RING_CLASS, GEM_CLASS, 0 };
  22.  
  23. static NEARDATA short disco[TOTAL_OBJS] = DUMMY;
  24.  
  25. int
  26. letindex(acls)
  27. register char acls;
  28. {
  29. register int i = 0;
  30. register char ch;
  31.     while ((ch = obj_symbols[i++]) != 0)
  32.         if (ch == acls) return(i);
  33.     return(0);
  34. }
  35.  
  36. static void
  37. setgemprobs()
  38. {
  39.     register int j, first;
  40.     int lev = (ledger_no(&u.uz) > maxledgerno())
  41.                 ? maxledgerno() : ledger_no(&u.uz);
  42.  
  43.     first = bases[letindex(GEM_CLASS)];
  44.  
  45.     for(j = 0; j < 9-lev/3; j++)
  46.         objects[first+j].oc_prob = 0;
  47.     first += j;
  48.     if (first > LAST_GEM || objects[first].oc_class != GEM_CLASS ||
  49.         OBJ_NAME(objects[first]) == NULL) {
  50.         raw_printf("Not enough gems? - first=%d j=%d LAST_GEM=%d",
  51.             first, j, LAST_GEM);
  52.         wait_synch();
  53.         }
  54.     for (j = first; j <= LAST_GEM; j++)
  55.         objects[j].oc_prob = (184+j-first)/(LAST_GEM+1-first);
  56. }
  57.  
  58. /* shuffle descriptions on objects o_low to o_high */
  59. static void
  60. shuffle(o_low, o_high, domaterial)
  61.     register int o_low, o_high;
  62.     register boolean domaterial;
  63. {
  64.     register int i, j;
  65. #ifdef TEXTCOLOR
  66.     int color;
  67. #endif /* TEXTCOLOR */
  68.     register short sw;
  69.  
  70.     for (j=o_low; j <= o_high; j++) {
  71.         i = o_low + rn2(j+1-o_low);
  72.         sw = objects[j].oc_descr_idx;
  73.         objects[j].oc_descr_idx = objects[i].oc_descr_idx;
  74.         objects[i].oc_descr_idx = sw;
  75. #ifdef TEXTCOLOR
  76.         color = objects[j].oc_color;
  77.         objects[j].oc_color = objects[i].oc_color;
  78.         objects[i].oc_color = color;
  79. #endif /* TEXTCOLOR */
  80.         /* shuffle material */
  81.         if (domaterial) {
  82.             sw = objects[j].oc_material;
  83.             objects[j].oc_material = objects[i].oc_material;
  84.             objects[i].oc_material = sw;
  85.         }
  86.     }
  87. }
  88.  
  89. void
  90. init_objects()
  91. {
  92. register int i, j, first, last, sum, end;
  93. register char acls;
  94. #ifdef TEXTCOLOR
  95. # define COPY_OBJ_DESCR(o_dst,o_src) \
  96.             o_dst.oc_descr_idx = o_src.oc_descr_idx,\
  97.             o_dst.oc_color = o_src.oc_color
  98. #else
  99. # define COPY_OBJ_DESCR(o_dst,o_src) o_dst.oc_descr_idx = o_src.oc_descr_idx
  100. #endif
  101.  
  102.     /* bug fix to prevent "initialization error" abort on Intel Xenix.
  103.      * reported by mikew@semike
  104.      */
  105.     for (i = 0; i < sizeof(obj_symbols); i++)
  106.         bases[i] = 0;
  107.     /* initialize object descriptions */
  108.     for (i = 0; i < TOTAL_OBJS; i++)
  109.         objects[i].oc_name_idx = objects[i].oc_descr_idx = i;
  110.     /* moved to after u_init()
  111.     init_artifacts();
  112.     */
  113.     /* init base; if probs given check that they add up to 1000,
  114.        otherwise compute probs; shuffle descriptions */
  115.     end = TOTAL_OBJS;
  116.     first = 0;
  117.     while( first < end ) {
  118.         acls = objects[first].oc_class;
  119.         last = first+1;
  120.         while (last < end && objects[last].oc_class == acls) last++;
  121.         i = letindex(acls);
  122.         if ((!i && acls != ILLOBJ_CLASS && acls != VENOM_CLASS) ||
  123.                                 bases[i] != 0)
  124.             error("initialization error for object class %d", acls);
  125.         bases[i] = first;
  126.  
  127.         if (acls == GEM_CLASS) setgemprobs();
  128.     check:
  129.         sum = 0;
  130.         for(j = first; j < last; j++) sum += objects[j].oc_prob;
  131.         if(sum == 0) {
  132.             for(j = first; j < last; j++)
  133.                 objects[j].oc_prob = (1000+j-first)/(last-first);
  134.             goto check;
  135.         }
  136.         if(sum != 1000)
  137.             error("init-prob error for %d (%d%%)", acls, sum);
  138.  
  139.         if (OBJ_DESCR(objects[first]) != NULL &&
  140.            acls != TOOL_CLASS && acls != WEAPON_CLASS && acls != ARMOR_CLASS) {
  141.  
  142.             /* shuffle, also some additional descriptions */
  143.             while (last < end && objects[last].oc_class == acls)
  144.             last++;
  145.             j = last;
  146.             if (acls == GEM_CLASS) {
  147.             if (rn2(2)) { /* change turquoise from green to blue? */
  148.                 COPY_OBJ_DESCR(objects[TURQUOISE],objects[SAPPHIRE]);
  149.             }
  150.             if (rn2(2)) { /* change aquamarine from green to blue? */
  151.                 COPY_OBJ_DESCR(objects[AQUAMARINE],objects[SAPPHIRE]);
  152.             }
  153.             switch (rn2(4)) { /* change fluorite from violet? */
  154.                 case 0:  break;
  155.                 case 1:    /* blue */
  156.                 COPY_OBJ_DESCR(objects[FLUORITE],objects[SAPPHIRE]);
  157.                 break;
  158.                 case 2:    /* white */
  159.                 COPY_OBJ_DESCR(objects[FLUORITE],objects[DIAMOND]);
  160.                 break;
  161.                 case 3:    /* green */
  162.                 COPY_OBJ_DESCR(objects[FLUORITE],objects[EMERALD]);
  163.                 break;
  164.             }
  165.             } else {
  166.             if (acls == POTION_CLASS)
  167.                 j--;  /* only water has a fixed description */
  168.             else if (acls == AMULET_CLASS ||
  169.                  acls == SCROLL_CLASS ||
  170.                  acls == SPBOOK_CLASS)
  171.                 do { j--; }
  172.                 while (!objects[j].oc_magic || objects[j].oc_unique);
  173.             /* non-magical amulets, scrolls, and spellbooks
  174.              * (ex. imitation Amulets, blank, scrolls of mail)
  175.              * and one-of-a-kind magical artifacts at the end of
  176.              * their class in objects[] have fixed descriptions.
  177.              */
  178.             shuffle(first, --j, TRUE);
  179.             }
  180.         }
  181.         first = last;
  182.     }
  183.  
  184.     /* shuffle the helmets */
  185.     shuffle(HELMET, HELM_OF_TELEPATHY, FALSE);
  186.  
  187.     /* shuffle the gloves */
  188.     shuffle(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY, FALSE);
  189.  
  190.     /* shuffle the cloaks */
  191.     shuffle(CLOAK_OF_PROTECTION, CLOAK_OF_DISPLACEMENT, FALSE);
  192.  
  193.     /* shuffle the boots [if they change, update find_skates() below] */
  194.     shuffle(SPEED_BOOTS, LEVITATION_BOOTS, FALSE);
  195. }
  196.  
  197. /* find the object index for snow boots; used [once] by slippery ice code */
  198. int
  199. find_skates()
  200. {
  201.     register int i;
  202.     register const char *s;
  203.  
  204.     for (i = SPEED_BOOTS; i <= LEVITATION_BOOTS; i++)
  205.     if ((s = OBJ_DESCR(objects[i])) != 0 && !strcmp(s, "snow boots"))
  206.         return i;
  207.     /* special case:  description of elven boots is nulled out for elf role */
  208.     if (pl_character[0] == 'E') return ELVEN_BOOTS;
  209.  
  210.     impossible("snow boots not found?");
  211.     return -1;    /* not 0, or caller would try again each move */
  212. }
  213.  
  214. void
  215. oinit()            /* level dependent initialization */
  216. {
  217.     setgemprobs();
  218. }
  219.  
  220. void
  221. savenames(fd)
  222. register int fd;
  223. {
  224.     register int i;
  225.     unsigned int len;
  226.  
  227.     bwrite(fd, (genericptr_t)bases, MAXOCLASSES * sizeof *bases);
  228.     bwrite(fd, (genericptr_t)disco, sizeof disco);
  229.     bwrite(fd, (genericptr_t)objects, sizeof(struct objclass) * TOTAL_OBJS);
  230.     /* as long as we use only one version of Hack we
  231.        need not save oc_name and oc_descr, but we must save
  232.        oc_uname for all objects */
  233.     for(i=0; i < TOTAL_OBJS; i++) {
  234.         if(objects[i].oc_uname) {
  235.             len = strlen(objects[i].oc_uname)+1;
  236.             bwrite(fd, (genericptr_t)&len, sizeof len);
  237.             bwrite(fd, (genericptr_t)objects[i].oc_uname, len);
  238.         }
  239.     }
  240. }
  241.  
  242. void
  243. restnames(fd)
  244. register int fd;
  245. {
  246.     register int i;
  247.     unsigned int len;
  248.  
  249.     mread(fd, (genericptr_t) bases, MAXOCLASSES * sizeof *bases);
  250.     mread(fd, (genericptr_t) disco, sizeof disco);
  251.     mread(fd, (genericptr_t) objects, sizeof(struct objclass) * TOTAL_OBJS);
  252.     for(i=0; i < TOTAL_OBJS; i++) {
  253.         if (objects[i].oc_uname) {
  254.             mread(fd, (genericptr_t) &len, sizeof len);
  255.             objects[i].oc_uname = (char *) alloc(len);
  256.             mread(fd, (genericptr_t)objects[i].oc_uname, len);
  257.         }
  258.     }
  259. }
  260.  
  261. void
  262. discover_object(oindx, mark_as_known)
  263. register int oindx;
  264. boolean mark_as_known;
  265. {
  266.     if (!objects[oindx].oc_name_known) {
  267.     register int dindx, acls = objects[oindx].oc_class;
  268.  
  269.     /* Loop thru disco[] 'til we find the target (which may have been
  270.        uname'd) or the next open slot; one or the other will be found
  271.        before we reach the next class...
  272.      */
  273.     for (dindx = bases[letindex(acls)]; disco[dindx] != 0; dindx++)
  274.         if (disco[dindx] == oindx) break;
  275.     disco[dindx] = oindx;
  276.  
  277.     if (mark_as_known) {
  278.         objects[oindx].oc_name_known = 1;
  279.         exercise(A_WIS, TRUE);
  280.     }
  281.     }
  282. }
  283.  
  284. /* if a class name has been cleared, we may need to purge it from disco[] */
  285. void
  286. undiscover_object(oindx)
  287. register int oindx;
  288. {
  289.     if (!objects[oindx].oc_name_known) {
  290.     register int dindx, acls = objects[oindx].oc_class;
  291.     register boolean found = FALSE;
  292.  
  293.     /* find the object; shift those behind it forward one slot */
  294.     for (dindx = bases[letindex(acls)];
  295.           dindx <= NROFOBJECTS && disco[dindx] != 0
  296.         && objects[dindx].oc_class == acls; dindx++)
  297.         if (found)
  298.         disco[dindx-1] = disco[dindx];
  299.         else if (disco[dindx] == oindx)
  300.         found = TRUE;
  301.  
  302.     /* clear last slot */
  303.     if (found) disco[dindx-1] = 0;
  304.     else impossible("named object not in disco");
  305.     }
  306. }
  307.  
  308. static boolean
  309. interesting_to_discover(i)
  310. register int i;
  311. {
  312.     return((boolean)(objects[i].oc_uname != NULL ||
  313.         (objects[i].oc_name_known && OBJ_DESCR(objects[i]) != NULL)));
  314. }
  315.  
  316. int
  317. dodiscovered()                /* free after Robert Viduya */
  318. {
  319.     register int i, dis;
  320.     int    ct = 0;
  321.     char *s, oclass, prev_class, classes[MAXOCLASSES];
  322.     winid tmpwin;
  323.  
  324.     tmpwin = create_nhwindow(NHW_MENU);
  325.     putstr(tmpwin, 0, "Discoveries");
  326.     putstr(tmpwin, 0, "");
  327.  
  328.     /* several classes are omitted from packorder; one is of interest here */
  329.     Strcpy(classes, flags.inv_order);
  330.     if (!index(classes, VENOM_CLASS)) {
  331.     s = eos(classes);
  332.     *s++ = VENOM_CLASS;
  333.     *s = '\0';
  334.     }
  335.  
  336.     for (s = classes; *s; s++) {
  337.     oclass = *s;
  338.     prev_class = oclass + 1;    /* forced different from oclass */
  339.     for (i = bases[letindex(oclass)];
  340.          i <= NROFOBJECTS && objects[i].oc_class == oclass; i++) {
  341.         if ((dis = disco[i]) && interesting_to_discover(dis)) {
  342.         ct++;
  343.         if (oclass != prev_class) {
  344.             putstr(tmpwin, ATR_INVERSE, let_to_name(oclass, FALSE));
  345.             prev_class = oclass;
  346.         }
  347.         putstr(tmpwin, 0, typename(dis));
  348.         }
  349.     }
  350.     }
  351.     if (ct == 0) {
  352.     You("haven't discovered anything yet...");
  353.     } else
  354.     display_nhwindow(tmpwin, TRUE);
  355.     destroy_nhwindow(tmpwin);
  356.  
  357.     return 0;
  358. }
  359.  
  360. /*o_init.c*/
  361.